function [colony F] = ImageAnalysisGUI(colony)

% Enrique Balleza, 3/31/10
% GUI derived from a GUI originally developed by Jeffrey Moffitt; jeffmoffitt@gmail.com

% This program provides a graphical user interface for a variety of image analysis programs
% -------------------------------------------------------------------------
% Directions:
% Click in the desired frame to select that frame
% Key commands:
% q: quit without saving data (data is returned as output if specified)
% e: run automatic edge finder
% c: run automated edge connector
% t: trim edges to the active frame
% m: enter user controlled edge connection for active frame
% s: save the colony
% l: get cells from edges
% i: Switch from phase to any flscnt images
% a: Toggle to edge addition mode
% d: Toggle to edge deletion mode



% Define Internal Functions
% ..........................................
    function HandleKeyPress(source, event)

        % Switch based on pressed character
        switch event.Character
            case 'q'
                % Quit without saving colony (current progress is returned in the output colony)
                userAnswer = questdlg('Quit: Leave figure open?'); % Add non-modal
                if strcmp(userAnswer, 'Yes')
                    set(fig_h, 'KeyPressFcn','');
                    set(fig_h, 'WindowButtonDownFcn', '');
                    set(fig_h, 'Name', ['colony ' colony.name ': inactive GUI']);
                    done =1;
                elseif strcmp(userAnswer, 'No');
                    close(fig_h);
                    done = 1;
                end

            case 'e'
                % Run automatic edge finder 'Percentile Thresholding'
                % .............................................
                title = 'Percentile Thresholding Options';
                prompt={'colony stripe width (um)', 'Percentil Threshold'};
                default = {'1.75', '0.80'};
                num_lines = 1;
                options = inputdlg(prompt, title, num_lines, default);
                
                if ~isempty(options)
                    colony = PercentileThresholding(colony, options);
                    if ishandle(ebf_h), delete(ebf_h); end
                    [fig_h ebf_h] = DisplayEdgesByFrame(colony, fig_h, ebf_h);
                else
                    display('Percentile Thresholding cancelled');
                end

            case 'c'
                title = 'Probabilistic Cell Tracking Options';
                prompt = {'Growth Rate SD (per pixel per frame)',...
                    'Number of Frames (All=[])'};
                default = {'0.02', '150'};
                num_lines = 1;
                options = inputdlg(prompt, title, num_lines, default);
                
                if ~isempty(options)
                    colony = ProbabilisticCellTrackingIV(colony, options, fig_h, api);
                else
                    display('Cell tracking cancelled');
                end

            case 't'
                % Trim smartEdges to active frame: allow corrections
                if ~isempty(frameID)
                    for i=1:length(colony.edges) % Remove all current paths
                        delete(colony.edges(i).h);
                        colony.edges(i).h = -1;
                    end
                    colony.edges = TrimEdges(colony.edges, frameID);
                    colony.edges = DisplayEdges(colony.edges, colony.bounds, fig_h);
                else
                    beep;
                    display('Select a frame');
                end

             case 'm'
                % Connect edges manually
                colony = ConnectEdgesManuallyIII(fig_h, colony);
                set(fig_h, 'Name', 'No Active Edge');
                set(fig_h, 'KeyPressFcn', @HandleKeyPress);
                set(fig_h, 'WindowButtonDownFcn', @HandleMouseDown);
                
            case 'l'
                DisplayCells(colony, fig_h);

            case 'i'
                % Toggle image display: for stacked images
                imageIndx = listdlg('PromptString', 'Select an image', 'SelectionMode', ...
                    'single', 'ListString', colony.channel);
                if ~isempty(imageIndx)
                    image = colony.image{imageIndx};
                    if ~strcmp(colony.channel{imageIndx}, 'PC') %Equalizes image. Useful to see dim and bright cells
                        image = imadjust(image); 
                    end 
                    image = im2uint8(mat2gray(image))';
                    set(im_h, 'CData', image);
                end

            case 's'
                % Save current colony
                uisave('colony', [savePath '\' colony.name]); 
                
            case 'a'
                % Toggle edge addition mode
                % ......................................
                edgeDeleteMode = 0;
                
                if edgeAddMode
                    set(fig_h, 'Name', 'No Active Frame');
                    frameID = [];
                    edgeAddMode = 0;
                else
                    edgeAddMode = 1;
                    set(fig_h, 'Name', 'Active Edge Addition');
                end
                
            case 'd'
                % Toggle edge deletion mode
                % ......................................                
                edgeAddMode = 0;
                
                if edgeDeleteMode
                    set(fig_h, 'Name', 'No Active Frame');
                    frameID = [];
                    edgeDeleteMode = 0;
                else
                    edgeDeleteMode = 1;
                    set(fig_h, 'Name', 'Active Edge Deletion');
                end
        end
    end

% -------------------------------------------------------------------------

    function HandleMouseDown(source, event)

        % Select active frame by mouse click
        % ......................................
        pnt = floor(get(gca, 'CurrentPoint'));
        frameID = floor(pnt(1,1)/(2*colony.margin(1)+1))+1;
                
        if ~edgeAddMode && ~edgeDeleteMode
            
            if ~isempty(frameID)
                set(fig_h, 'Name', ['Active frame ' num2str(frameID)]);
            else
                set(fig_h, 'Name', 'No Active Frame');
            end
            
        elseif edgeAddMode
            
            edges = colony.edgesByFrame(frameID).edges;            
            
            lineAv = colony.lineAv(frameID,:);
            [~,newEdge] = min(((1:length(lineAv)) - pnt(1,2)).^2);
            prob = colony.edgesByFrame(frameID).prob;

            %Estimate newEdge with subpixel resolution
            %............................................................
            %Get local profile around newEdge
            range = 12;
            profile = lineAv(newEdge-range:newEdge+range);
            
            %Get approx position of maxima
            threshold = colony.thresholdOpt.threshold;
            nProfile = length(profile);
            profileSrtd = sort(profile);
            outbot = profileSrtd(ceil(nProfile*threshold));
            maxs = GetPositionMaxima(profile, outbot) + (newEdge-range) - 1;
            [~,indx] = min((maxs-pnt(1,2)).^2);
            edgeRefined = maxs(indx);

            %Apply subpixel resolution
            rawlineAv = colony.rawlineAv(frameID,:);
            newEdge = AplyAntiAliasing(edgeRefined, rawlineAv);
            %............................................................
            
            if ~ismember(edges, newEdge)
                indx = length(find(edges < newEdge));
                switch indx
                    case 0
                        edges = [newEdge edges];
                        prob = [1 prob];
                    case length(edges)
                        edges = [edges newEdge];
                        prob = [prob 1];
                    otherwise
                        edges = [edges(1:indx) newEdge edges(indx+1:end)];
                        prob = [prob(1:indx) 1 prob(indx+1:end)];
                end
                if ishandle(ebf_h(frameID))
                    xPos = bounds(frameID)*ones(1, length(edges)) + (2*colony.margin(1)+1)/2;
                    set(ebf_h(frameID), 'XData', xPos, 'YData', edges);
                end
                colony.edgesByFrame(frameID).edges = edges;
                colony.edgesByFrame(frameID).prob = prob;
            end
            
        else % edgeDeleteMode
            
            edges = colony.edgesByFrame(frameID).edges;
            
            [~,selectedInd] = min((edges - pnt(1,2)).^2);
                        
            if ~isempty(selectedInd)
                edges = setdiff(edges, edges(selectedInd));
                if ishandle(ebf_h(frameID))
                    xPos = bounds(frameID)*ones(1, length(edges)) + (2*colony.margin(1)+1)/2;
                    set(ebf_h(frameID), 'XData', xPos, 'YData', edges);
                end
                if isfield(colony.edgesByFrame, 'prob')
                    prob = colony.edgesByFrame(frameID).prob;
                    mask = ones(1,length(edges)+1);
                    mask(selectedInd) = 0;
                    colony.edgesByFrame(frameID).prob = prob(mask==1);
                end
                colony.edgesByFrame(frameID).edges = edges;
            end

        end

    end


% Main
% -----------------------------------------------------
fig_h = figure('Name', 'No Active Frame');

PC_low = colony.image{end};

% PC_low = imadjust(PC); %Equalizes the image.Useful to see dim and bright cells
PC_low = im2uint8(mat2gray(PC_low))';
im_h = image(PC_low);
colormap(gray(2^8));
set(im_h, 'CDataMapping', 'direct');
sp_h = imscrollpanel(fig_h, im_h);
immagbox(fig_h, im_h);

axis ij;
hold on;
axis manual;

bounds = colony.bounds;

pos = get(fig_h, 'Position');
set(fig_h, 'Position', [pos(1) 50 pos(3) size(PC_low,1)+40]);


%Set initial position of visible region
%..........................................
api = iptgetapi(sp_h);
api.setMagnification(1)
api.setVisibleLocation([0 0]);
if isfield(colony, 'edges')

    frameID = 1;
    for edge=colony.edges, frameID = max([frameID edge.frameID]); end

    show_Frames = 4; %Conected number of frames to show

    width = bounds(2) - bounds(1);
    imrect = api.getVisibleImageRect();  %[xmin ymin width height]
    x_max = width*length(bounds) - imrect(3) + 1;
    x_visLoc = width*(frameID-show_Frames) + 1;
    if x_visLoc<0, x_visLoc = 0; end
    if x_visLoc >= x_max
        x_visLoc = x_max;
    end
    api.setVisibleLocation([x_visLoc 0])

end


% Create frame labels
% .............................................
middle = (bounds(2) - bounds(1))/2;
for j=1:length(bounds)
    XPos = bounds(j) + middle;
    YPos = 12 + ((-1)^j)*5;
    text(XPos, YPos, num2str(j), 'Color', 'r');
end


% Define save path
% ........................................
savePath = colony.origin.annotationPath;


% Initialize edge click modes
% ...........................................
edgeDeleteMode = 0;
edgeAddMode = 0;


% Define window callback functions
% ....................................................
set(fig_h, 'KeyPressFcn', @HandleKeyPress);
set(fig_h, 'WindowButtonDownFcn', @HandleMouseDown);
set(fig_h, 'MenuBar', 'none');


% Define semi-global variables
% ..........................................
ebf_h = [];
frameID = [];


% Initial display options
% ......................................................
%To do: Update DisplayEdgesByFrame and DisplayEdges with a rational use of graphical resources
if isfield(colony, 'edgesByFrame')
    if ~isempty(colony.edgesByFrame)
        [fig_h, ebf_h] = DisplayEdgesByFrame(colony, fig_h, ebf_h);
    end
end

if isfield(colony, 'edges')
    if ~isempty(colony.edges)
        colony.edges = DisplayEdges(colony.edges, colony.bounds, fig_h);
    end
end


% Wait for user to close function
% ..............................................
done = 0;
while ~done && ishandle(fig_h)
    waitfor(fig_h, 'CurrentCharacter');
end

end
